#coding=utf8
'''
Low level interface to datasets of DTAUS
.. warning:
   do not use this directly !
'''
import const
import const.setA as constA

import datetime

class DTAUS(object):
    '''
    Masterclass representing a full collection of DTAUS sets (A, C and E) for creation of a DTAUS-textfile
    '''

    def __init__(self):
        pass
        
    class SetA(object):
        '''
        Subclass representing the dataset typ 'A' of DTAUS
        '''
        
    
        def __init__(self,
                     transaction,
                     BLZrcv,
                     namesnd,
                     acctsnd,
                     BLZsnd='00000000',
                     creation_date='today',
                     execution_date=const.alpha_fillchar*8,
                     refno='0000000000',
                     currency='EUR'
                     ):
            '''
            Parameters:
            - transaction: type of transaction, see const.setA.get_transactiontypes()
            - BLZrcv: BLZ of receiver (i.e. your Bank)
            - namesnd: name of sender
            - acctsnd: account number of sender
            - BLZsnd: BLZ of sender ('00000000' if sender is not a bank)
            - creation_date: date of creation of DTAUS-file in format 'DDMMYY' (or 'today')
            - execution_date: if transaction shouldn't be executed asap, enter date in format 'DDMMYYYY'
            - refno: reference number or '0000000000'
            - currency: see const.setA.get_currencies() , default is 'EUR' -> ' '
            '''
            
            # Type of transaction
            if transaction not in constA.get_transactiontypes():
                raise Exception('wrong transactiontype')
            self.transaction = transaction
            
            # BLZ of receiver (i.e. you bank)
            if len(BLZrcv) <> 8 or not BLZrcv.isdigit():
                raise Exception('BLZ of receiver has no correct length')
            self.BLZrcv = BLZrcv
            
            # BLZ of sender (has to be '00000000' if sender is not a bank) 
            if len(BLZsnd) <> 8 or not BLZsnd.isdigit():
                raise Exception('BLZ of sender has no correct length')
            self.BLZsnd = BLZsnd
            
            #Name of Sender
            self.namesnd = namesnd.ljust(27,const.alpha_fillchar)[:27].upper()
            if self.namesnd == const.alpha_fillchar * 27:
                raise Exception('Name of sender not set') 
        
            # Creation date
            if creation_date.upper() == 'TODAY':
                today = datetime.date.today()
                self.creation_date = str(today.day).rjust(2,'0') + str(today.month).rjust(2,'0') + str(today.year)[-2:]
            else:
                self.creation_date = creation_date
            if not self.creation_date.isdigit or len(self.creation_date) <> 6:
                raise Exception('creation date has no correct format (DDMMYY,digits)')
                
            # Account of sender
            self.acctsnd = acctsnd.rjust(10,'0')
            if not self.acctsnd.isdigit() or len(self.acctsnd) <> 10:
                raise Exception('Accountnumber of sender not correct')
            
            # Reference (numeric)
            self.refno = refno.rjust(10,'0')
            if not self.refno.isdigit() or len(self.refno) <> 10:
                raise Exception('Reference number not correct')
            
            # Execution date
            self.execution_date = execution_date
            if len(self.execution_date) <> 8:
                raise Exception('Execution date not in correct format (DDMMYYYY or 8*space)')
            if not (self.execution_date.isdigit() or self.execution_date <> const.alpha_fillchar*8):
                raise Exception('Execution date invalid')
            
            # Currency
            currency = currency.upper()
            if currency in constA.get_currencies():
                self.currency = constA.currency[currency]
            if not self.currency in constA.currency.values():
                raise Exception('currency invalid')
            
            
        def _create_string(self):
            output = ""
            
            #field 1 - length (has to be 128):
            output += "0128"
            
            #field 2 - set type (always "A")
            output += constA.type_of_set
            
            #field 3 - type of transaction
            output += self.transaction
            
            #field 4 - BLZ of file recipient (d. i. Auftraggeberbank)
            output += self.BLZrcv
            
            #field 5 - BLZ of sender ('00000000' if not a bank)
            output += self.BLZsnd
            
            #field 6 - Name of sender
            output += self.namesnd
            
            #field 7 - creation date
            output += self.creation_date
            
            #field 8 - filler
            output +=  const.alpha_fillchar * 4
            
            #field 9 - Account number of sender
            output += self.acctsnd
            
            #field 10- Reference number
            output += self.refno
            
            #field 11a- filler
            output += const.alpha_fillchar * 15
            #field 11b- Execution date
            output += self.execution_date
            #field 11c- filler
            output += const.alpha_fillchar * 24
            
            #field 12- currency
            output += self.currency
            
            if len(output) <> const.setA.length_of_set_num:
                raise Exception('Length of set A incorrect')
            
            return output
        
        def __repr__(self):
            return self._create_string()
    
    class SetC(object):
        '''
           Subclass representing the dataset typ 'C' of DTAUS
        '''
        
        def __init__(
                     self,
                     setLength,
                     targetBLZ,
                     targetAcct,
                     txtKey,
                     
                     txtKeyExt='000',
                     firstBankBLZ='00000000',
                     internalNum='0'*13,
                     ):
            pass
     
    class SetE(object):
        '''
        Subclass representing the dataset typ 'E' of DTAUS
        '''
        
        def __init__(
                     self,
                     setCcount,
                     sumAccountNums,
                     sumBLZ,
                     sumEUR='0'*13,
                     sumDM='0'*13
                     ):
            '''
            Parameters:
                - setCcount: Number of type 'C' datasets
                - sumAccountNums: Sum of Account Numbers in type 'C' datasets
                - sumBLZ: Sum of BLZ-numbers in type 'C' datasets
                - sumEUR: Sum of amounts in EUR
                - sumDM: Sum of amounts in DM
            '''
            
            if type(setCcount) == type (int()):
                setCcount = str(setCcount)
            if type(setCcount) <> type(str()):
                raise Exception('Count of setC is not a string')
            if len(setCcount) > 7:
                raise Exception('Count of setC is too big')
            self.setCcount = setCcount.rjust(7,'0')
            
            if not type(sumAccountNums) == type(str()):
                raise Exception('Sum of account numbers is not a string')
            if not sumAccountNums.isdigit():
                raise Exception('Sum of account numbers is not a digit')
            if len(sumAccountNums) > 17:
                raise Exception('Sum of account numbers is too big')
            self.sumAccountNums = sumAccountNums.rjust(17,'0')
            
            if not type(sumBLZ) == type(str()):
                raise Exception('Sum of BLZ is not a string')
            if not sumBLZ.isdigit():
                raise Exception('Sum of BLZ is not a digit')
            if len(sumBLZ) > 17:
                raise Exception('Sum of BLZ is too big')
            self.sumBLZ = sumBLZ.rjust(17,'0')
            
            if type(sumEUR) <> type(str()):
                raise Exception('Sum of EUR amounts is not a string')
            if not sumEUR.isdigit():
                raise Exception('Sum of EUR amounts is not a digit')
            if len(sumEUR) > 17:
                raise Exception('Sum of EUR amounts is too big')
            self.sumEUR = sumEUR.rjust(17,'0')
            
            if type(sumDM) <> type(str()):
                raise Exception('Sum of DM amounts is not a string')
            if not sumDM.isdigit():
                raise Exception('Sum of DM amounts is not a digit')
            if len(sumDM) > 17:
                raise Exception('Sum of DM amounts is too big')
            self.sumDM = sumDM
        
        def _create_string(self):
            #field 1 - Lenght of set
            output =  const.setE.length_of_set_num
            # field 2 - Type of Set
            output += const.setE.type_of_set
            # field 3 - count of type 'C' datasets
            output += self.setCcount
            # field 4 - filler
            output += const.alpha_fillchar * 5
            # field 5 - sum of amounts in DM - '0000000000000' since EURO
            output += self.sumDM
            # field 6 - sum of account numbers
            output += self.sumAccountNums
            # field 7 - sum of BLZ
            output += self.sumBLZ
            #field8 - sum of EUR amounts
            output += self.sumEUR
            #filed 9- filler
            output += const.alpha_fillchar * 51
            
            #TODO: add length-checking here and throw Exception if not matching
            return output
         
        def __repr__(self):
            pass
        
        